#include "../config.h"

#ifdef USE_GROWL

#include <stdlib.h>
#include <Growl/Growl.h>

static int _initted = 0;
static int _appicon_copied = 0;
struct Growl_Delegate _delegate;

int growl_init(const char **notifications,
               const char  *icon_data,
               size_t       icon_data_size,
               int          copy_icon_data) {
  if (!_initted && Growl_IsInstalled() && Growl_IsRunning()) {
    InitGrowlDelegate(&_delegate);
    _delegate.applicationName = CFSTR(PACKAGE_STRING);
    if (icon_data && icon_data_size) {
      if ((_appicon_copied = copy_icon_data)) {
        _delegate.applicationIconData = CFDataCreate(NULL, icon_data, icon_data_size);
      } else {
        _delegate.applicationIconData =
          CFDataCreateWithBytesNoCopy(NULL, icon_data, icon_data_size, kCFAllocatorNull);
      }
    }

    size_t notifs_count = 0;
    const char **n;
    for(n = notifications; *n; ++n) ++notifs_count;
    CFTypeRef *notifs = (CFTypeRef *)malloc(sizeof(CFTypeRef) * notifs_count);
    size_t i;
    for(i = 0; i < notifs_count; ++i) {
      notifs[i] = CFStringCreateWithCString(kCFAllocatorDefault, notifications[i], kCFStringEncodingUTF8);
    }

    CFTypeRef keys[] = {
      GROWL_NOTIFICATIONS_ALL,
      GROWL_APP_ID
    };
    CFArrayRef notif_ary = CFArrayCreate(NULL, notifs, notifs_count, &kCFTypeArrayCallBacks);
    CFTypeRef values[] = {
      notif_ary,
      CFSTR("org.gpyp3")
    };
    CFDictionaryRef dict = CFDictionaryCreate(NULL,
                                              keys,
                                              values,
                                              sizeof(keys) / sizeof(CFTypeRef),
                                              &kCFTypeDictionaryKeyCallBacks,
                                              &kCFTypeDictionaryValueCallBacks);
    _delegate.registrationDictionary = dict;
    Growl_SetDelegate(&_delegate);
    CFRelease(notif_ary);
    for(i = 0; i < notifs_count; ++i) CFRelease(notifs[i]);
    free(notifs);
    return _initted = 1;
  }
  return 0;
}
void growl_uninit() {
  Growl_SetDelegate(NULL);
  CFRelease(_delegate.registrationDictionary);
  if (_delegate.applicationIconData && _appicon_copied) CFRelease(_delegate.applicationIconData);
  InitGrowlDelegate(&_delegate);
  _initted = false;
}
int growl_is_initted() {
  return _initted;
}

void growl_post_notification(const char *name,
                             const char *title,
                             const char *description,
                             int         priority,
                             const char *icon_data,
                             size_t      icon_data_size) {
  struct Growl_Notification n;
  InitGrowlNotification(&n);
  n.name        = CFStringCreateWithCString(NULL, name,        kCFStringEncodingUTF8);
  n.title       = CFStringCreateWithCString(NULL, title,       kCFStringEncodingUTF8);
  n.description = CFStringCreateWithCString(NULL, description, kCFStringEncodingUTF8);
  n.priority    = priority;
  if (icon_data && icon_data_size) {
    n.iconData = CFDataCreateWithBytesNoCopy(NULL, icon_data, icon_data_size, kCFAllocatorNull);
  }
  Growl_PostNotification(&n);
  CFRelease(n.name);
  CFRelease(n.title);
  CFRelease(n.description);
}

#endif

